package framework.eea.entity;

/**
 *
 * @author Markus Schr&ouml;der
 */
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import framework.eea.StateBasedGame;
import framework.eea.gui.Graphics;
import framework.eea.gui.JFrameGameContainer;

/**
 * The StateBasedEntityManager is responsible for updating entities based on the current state of the game, as well as detecting collisions based on the current game state.
 *
 * Note that the programmer can <em>not</em> create a new instance of this object. Instead, retrieve the current instance using the static method
 * {@link eea.engine.entity.StateBasedEntityManager#getInstance()}.
 *
 * @author Alexander Jandousek, Timo B&auml;hr
 * @version 1.0
 */
public class EntityManager {

    private static final EntityManager entityManager = new EntityManager();
    
    private final Map<Integer, List<Entity>> entities = new HashMap<Integer, List<Entity>>();

    
    public static EntityManager getInstance() {
        return entityManager;
    }
    private EntityManager() {
        
    }

    
    public void addEntity(int state, Entity entity) {
        entities.get(Integer.valueOf(state)).add(entity);
    }

    /**
     * adds a new state with the given state ID
     *
     * @param stateID the ID for the new state
     */
    public void addState(int stateID) {
        entities.put(stateID, new LinkedList<Entity>());
    }

    /**
     * clears the entities from all states
     */
    public void clearAllStates() {
        entities.clear();
    }

    public void clearEntitiesFromState(int stateID) {
        entities.get(Integer.valueOf(stateID)).clear();
    }

    /*
    public Entity collides(int gameState, Entity entity) {
        // retrieve all entities from the list of entities
        List<Entity> candidates = entities.get(Integer.valueOf(gameState));
        // if there is such a state with entities...
        if (candidates == null || entity == null) {
            return null; // cannot have a collision with "nothing"
        }
        // ...then iterate over them...
        Iterator<Entity> iterator = candidates.iterator();
        while (iterator.hasNext()) {
            // ... and check each if they collide with "entity"
            Entity tempEntity = iterator.next();
            if (entity.collides(tempEntity)) {
                return tempEntity;
            }

        }
        // no collision found, thus return null
        return null;
    }*/

    
    public List<Entity> getEntitiesByState(int stateID) {
        return entities.get(Integer.valueOf(stateID));
    }

    
    public Entity getEntity(int state, String name) {
        List<Entity> stepEntities = entities.get(Integer.valueOf(state));
        if (stepEntities == null || name == null) {
            return null; // stop here, cannot be successful!
        }
        // retrieve the iterator for the selected state
        Iterator<Entity> iterator = stepEntities.iterator();

        // while there are more entities...
        while (iterator.hasNext()) {
            Entity entity = iterator.next();
            // if found, return it
            if (name.equals(entity.getID())) {
                return entity;
            }
        }

        // nothing found, return null
        return null;
    }

    public boolean hasEntity(int state, String prefix) {
        List<Entity> chosen = entities.get(Integer.valueOf(state));
        if (prefix == null || chosen == null) {
            return false; // cannot be successful!
        }
        Iterator<Entity> iterator = chosen.iterator();
        // iterate over all candidates...
        while (iterator.hasNext()) {
            Entity entity = iterator.next();
            if (entity.getID().startsWith(prefix)) // and return true once the first match is found
            {
                return true;
            }
        }

        // nothing found
        return false;
    }

    public void removeEntity(int state, Entity entity) {
        entities.get(Integer.valueOf(state)).remove(entity);
    }
    
    public void removeEntityByID(int state, String name) {
        removeEntity(state, getEntity(state, name));
    }

    public void renderEntities(JFrameGameContainer gc, StateBasedGame sb, Graphics graphicsContext) {
        // retrieve all entities from the current game state
        List<Entity> candidates = entities.get(Integer.valueOf(sb
                .getCurrentStateID()));
        // if there is such a state with entities...
        if (candidates != null) {
            // ...then iterate over them...
            Iterator<Entity> iterator = candidates.iterator();
            while (iterator.hasNext()) {
                // ... and ask them to render themselves
                iterator.next().render(gc, sb, graphicsContext);
            }
        }
    }

    public void setEntityListByState(int stateID, List<Entity> targetEntities) {
        entities.put(Integer.valueOf(stateID), targetEntities);
    }

    public void updateEntities(JFrameGameContainer gc, StateBasedGame sb, int delta) {
        // retrieve all entities from the current game state
        List<Entity> candidates = entities.get(Integer.valueOf(sb
                .getCurrentStateID()));
        // if there is such a state with entities...
        if (candidates != null) {
            // ...then iterate over them...
            Iterator<Entity> iterator = candidates.iterator();
            while (iterator.hasNext()) {
                // .. and them them to update themselves
                iterator.next().update(gc, sb, delta);
            }
        }
    }
}
